package com.shell.governor.organization.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.persistence.service.impl.PersistentServiceImpl;
import com.shell.governor.modules.service.PubBusinessService;
import com.shell.governor.organization.dao.PubOrganDao;
import com.shell.governor.organization.dao.PubOrganTypeDao;
import com.shell.governor.organization.po.PubOrgan;
import com.shell.governor.organization.po.PubOrganType;
import com.shell.governor.organization.po.PubStru;
import com.shell.governor.organization.service.PubOrganService;
import com.shell.governor.organization.service.PubStruService;
import com.shell.governor.organization.vo.PubOrganVo;
import com.shell.governor.user.dao.PubUserExtraDao;
import com.shell.governor.user.dao.PubUserOrganDao;
import com.shell.governor.user.po.PubUserExtra;
import com.shell.governor.user.po.PubUserOrgan;

import tk.mybatis.mapper.entity.Example;

@Service
public class PubOrganServiceImpl extends PersistentServiceImpl<PubOrgan> implements PubOrganService {
	@Autowired
	private PubOrganDao pubOrganDao;
	@Autowired
	private PubOrganTypeDao pubOrganTypeDao;
	@Autowired
	private PubStruService pubStruService;
	@Autowired
	private PubUserOrganDao pubUserOrganDao;
	@Autowired
	private PubUserExtraDao pubUserExtraDao;
	@Autowired
	private PubBusinessService pubBusinessService;
	
	final String CORE_ORGANTYPE_KEY = "core.organ.permission.organType";
	final String CORE_STRULEVEL_KEY = "core.organ.permission.struLevel";
	final String SELF_RULE_KEY = "self.organ.permission.rule";

	public int saveOrUpdateOrganRecord(PubOrganVo pubOrganVo) {
		int result = 0;
		PubOrgan organ = null;
		if (StringUtil.notTrimEmpty(pubOrganVo.getOrganId())) {
			organ = (PubOrgan) selectByKey(pubOrganVo.getOrganId());
		}
		if (StringUtil.notTrimEmpty(pubOrganVo.getParentCode())) {
			PubOrgan parentOrgan = new PubOrgan();
			parentOrgan.setOrganCode(pubOrganVo.getParentCode());
			parentOrgan = (PubOrgan) selectOne(parentOrgan);
			if (parentOrgan == null) {
				throw new UnCheckMsgException("��������������������������");
			}
			pubOrganVo.setParentId(parentOrgan.getOrganId());
		}
		PubStru pubStru = checkParam(pubOrganVo);
		if (pubStru != null) {
			if ((organ == null) || (StringUtil.emptyAndNull(pubOrganVo.getOrganId()))) {
				organ = new PubOrgan();
				if (StringUtil.emptyAndNull(pubOrganVo.getOrganId())) {
					pubOrganVo.setOrganId(SystemUtil.getUUID());
					pubStru.setOrganId(pubOrganVo.getOrganId());
				}
				BeanUtils.copyProperties(pubOrganVo, organ);
				if (StringUtil.emptyAndNull(organ.getOrganType())) {
					organ.setOrganType(" ");
				}
				result = this.pubOrganDao.insert(organ);
			} else {
				BeanUtils.copyProperties(pubOrganVo, organ);
				if (StringUtil.emptyAndNull(organ.getOrganType())) {
					organ.setOrganType(" ");
				}
				result = this.pubOrganDao.updateByPrimaryKey(organ);
			}
			result = this.pubStruService.savePubStruRecord(pubStru);
		}
		if (StringUtil.notEmpty(pubOrganVo.getBizCodes())) {
			this.pubBusinessService.openBizByCodes(pubOrganVo.getOrganId(), pubOrganVo.getBizCodes());
		}
		if (StringUtil.notEmpty(pubOrganVo.getBizIds())) {
			this.pubBusinessService.openBizByBizIds(pubOrganVo.getOrganId(), pubOrganVo.getBizIds());
		}
		return result;
	}

	public List<PubOrganVo> queryOrganTree(PubOrganVo pubOrganVo) {
		if (StringUtil.notEmpty(pubOrganVo.getOrganName())) {
			pubOrganVo.setOrganName(StringUtil.getParameterLike(pubOrganVo.getOrganName()));
		}
		if ((StringUtil.notEmpty(pubOrganVo.getStruPath())) && (!pubOrganVo.getStruPath().contains("%"))) {
			pubOrganVo.setStruPath(StringUtil.getParameterLike(pubOrganVo.getStruPath()));
		}
		List<PubOrganVo> organVos = this.pubOrganDao.queryOrganMsgByCondition(pubOrganVo);
		for (PubOrganVo org : organVos) {
			if (!StringUtil.emptyAndNull(org.getStruPath())) {
				String[] id = org.getStruPath().split(";");
				String parentName = "";
				for (int i = 0; i < id.length; i++) {
					PubOrgan parentOrg = (PubOrgan) this.pubOrganDao.selectByPrimaryKey(id[i]);
					parentName = parentName + parentOrg.getOrganName() + "_";
				}
				org.setParentName(parentName);
			}
		}
		List<PubOrganVo> organTreeList = new ArrayList<PubOrganVo>();
		genSubOrganTree(organVos, organTreeList, 0, pubOrganVo.getStruLevel().intValue());
		return organTreeList;
	}

	private int genSubOrganTree(List<PubOrganVo> organs, List<PubOrganVo> children, int start, int level) {
		int index = start;
		while (index < organs.size()) {
			PubOrganVo organVo = (PubOrganVo) organs.get(index);
			if (organVo.getStruLevel().intValue() == level) {
				children.add(organVo);
				organVo.setChildren(new ArrayList<PubOrganVo>());
				index = genSubOrganTree(organs, organVo.getChildren(), index + 1, level + 1);
				if ((organVo.getChildren() != null) && (organVo.getChildren().size() == 0)) {
					organVo.setChildren(null);
				}
			} else {
				if (organVo.getStruLevel().intValue() < level) {
					break;
				}
				if (organVo.getStruLevel().intValue() > level) {
					index = genSubOrganTree(organs, children, index, organVo.getStruLevel().intValue());
				}
			}
		}
		if (children.size() > 0) {
			Collections.sort(children, new Comparator<PubOrganVo>() {
				@Override
				public int compare(PubOrganVo arg0, PubOrganVo arg1) {
					return arg0.getStruLevel().compareTo(arg1.getStruLevel());
				}
			});
		}
		return index;
	}

	private PubStru checkParam(PubOrganVo pubOrganVo) {
		PubStru stru = null;
		if (pubOrganVo != null) {
			stru = new PubStru();
			stru.setOrganId(pubOrganVo.getOrganId());
			if (StringUtil.notEmpty(pubOrganVo.getStruType())) {
				stru.setStruType(pubOrganVo.getStruType());
			}
			if (StringUtil.notEmpty(pubOrganVo.getStruPath())) {
				stru.setStruPath(pubOrganVo.getStruPath());
			}
			if (pubOrganVo.getStruLevel() != null) {
				stru.setStruLevel(pubOrganVo.getStruLevel());
			}
			if (StringUtil.notEmpty(pubOrganVo.getParentId())) {
				stru.setParentId(pubOrganVo.getParentId());
			}
		}
		return stru;
	}

	public PubOrganVo selectOrganById(String organId) {
		PubOrganVo pubOrganVo = new PubOrganVo();
		String parentName = this.pubOrganDao.selectParentName(organId);
		PubOrgan organ = (PubOrgan) selectByKey(organId);
		pubOrganVo.setOrganId(organ.getOrganId());
		pubOrganVo.setOrganCode(organ.getOrganCode());
		pubOrganVo.setOrganName(organ.getOrganName());
		pubOrganVo.setOrganState(organ.getOrganState());
		pubOrganVo.setOrganType(organ.getOrganType());
		pubOrganVo.setShortName(organ.getShortName());
		pubOrganVo.setParentName(parentName);
		PubStru stru = new PubStru();
		stru.setOrganId(organ.getOrganId());
		stru = (PubStru) this.pubStruService.selectOne(stru);
		if (stru != null) {
			pubOrganVo.setStruLevel(stru.getStruLevel());
			pubOrganVo.setStruPath(stru.getStruPath());
			pubOrganVo.setStruType(stru.getStruType());
		}
		PubOrganType pot = (PubOrganType) this.pubOrganTypeDao.selectByPrimaryKey(organ.getOrganType());
		if (pot != null) {
			pubOrganVo.setTypeName(pot.getTypeName());
		}
		return pubOrganVo;
	}

	public int updateOrganStateWithCascade(String organId, String parentId, String organState) {
		int result = this.pubOrganDao.updateOrganStateWithCascade("%" + organId + "%", organState);
		if ((result > 0) && (StringUtil.notEmpty(parentId)) && (organState.equals("E"))) {
			List<PubOrganVo> list = this.pubOrganDao.selectOrganStru(parentId, "E");
			if (list.size() > 0) {
				PubOrgan po = new PubOrgan();
				po.setOrganId(parentId);
				po.setOrganState(organState);
				this.pubOrganDao.updateByPrimaryKeySelective(po);
			}
		}
		return result;
	}

	public boolean checkCodeUnique(PubOrgan pubOrgan) {
		if (StringUtil.trimEmpty(pubOrgan.getOrganCode())) {
			return true;
		}
		Example example = new Example(PubOrgan.class);
		Example.Criteria criteria = example.createCriteria();
		if (!StringUtil.trimEmpty(pubOrgan.getOrganId())) {
			criteria.andNotEqualTo("organId", pubOrgan.getOrganId());
		}
		criteria.andEqualTo("organCode", pubOrgan.getOrganCode());
		criteria.andNotEqualTo("organState", "D");

		List<PubOrgan> list = selectByExample(example);
		if (list.size() > 0) {
			return false;
		}
		return true;
	}

	public boolean checkOrganNameUnique(PubOrgan pubOrgan) {
		if (StringUtil.trimEmpty(pubOrgan.getOrganName())) {
			return true;
		}
		Example example = new Example(PubOrgan.class);
		Example.Criteria criteria = example.createCriteria();
		if (!StringUtil.trimEmpty(pubOrgan.getOrganId())) {
			criteria.andNotEqualTo("organId", pubOrgan.getOrganId());
		}
		criteria.andEqualTo("organName", pubOrgan.getOrganName());

		List<PubOrgan> list = selectByExample(example);
		if (list.size() > 0) {
			return false;
		}
		return true;
	}

	public PubOrganVo queryUserEnt(String organId, String userId) {
		PubUserOrgan uo = new PubUserOrgan();
		uo.setDeptId(organId);
		uo.setUserId(userId);
		uo = (PubUserOrgan) this.pubUserOrganDao.selectOne(uo);
		if (uo != null) {
			PubOrganVo organVo = selectOrganById(uo.getEntId());

			return organVo;
		}
		return null;
	}

	public PubOrganVo selectOrganByUserId(String userId) {
		Example example = new Example(PubUserOrgan.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo("userId", userId);
		List<PubUserOrgan> orgList = this.pubUserOrganDao.selectByExample(example);
		PubOrganVo organ = null;
		if ((orgList != null) && (orgList.size() > 0)) {
			organ = selectOrganById(((PubUserOrgan) orgList.get(0)).getDeptId());
		}
		return organ;
	}

	public List<PubOrgan> selectOrgan(PubOrgan organ) {
		Example example = getOrganExample(organ);

		return this.pubOrganDao.selectByExample(example);
	}

	private Example getOrganExample(PubOrgan organ) {
		Example example = new Example(PubOrgan.class);
		Example.Criteria criteria = example.createCriteria();
		if (!StringUtil.emptyAndNull(organ.getOrganState())) {
			criteria.andEqualTo("organState", organ.getOrganState());
		} else {
			criteria.andNotEqualTo("organState", "D");
		}
		if (StringUtil.notEmpty(organ.getOrganId())) {
			criteria.andEqualTo("organId", organ.getOrganId());
		}
		if (StringUtil.notEmpty(organ.getOrganCode())) {
			criteria.andEqualTo("organCode", organ.getOrganCode());
		}
		if (StringUtil.notEmpty(organ.getOrganName())) {
			criteria.andEqualTo("organName", organ.getOrganName());
		}
		if (StringUtil.notEmpty(organ.getOrganType())) {
			criteria.andEqualTo("organType", organ.getOrganType());
		}
		if (StringUtil.notEmpty(organ.getShortName())) {
			criteria.andEqualTo("shortName", organ.getShortName());
		}
		return example;
	}

	public List<PubOrganVo> selectOrganVoByOrgan(PubOrgan organ) {
		if (organ == null) {
			return null;
		}
		return this.pubOrganDao.queryOrganMsgByCondition((PubOrganVo) organ);
	}

	public PubOrgan getEntByOrganId(String organId) {
		PubStru stru = new PubStru();
		stru.setOrganId(organId);
		stru.setStruType("0");
		stru = (PubStru) this.pubStruService.selectOne(stru);
		String[] pathIds = stru.getStruPath().split(";");
		for (int i = pathIds.length - 1; i >= 0; i--) {
			PubOrgan organ = (PubOrgan) selectByKey(pathIds[i]);
			if ("ENT".equals(organ.getOrganType())) {
				return organ;
			}
		}
		return null;
	}

	public List<PubOrganVo> queryUserEnt(String userId) {
		PubUserOrgan userOrgan = new PubUserOrgan();
		userOrgan.setUserId(userId);
		userOrgan.setValid("1");
		List<PubUserOrgan> uos = this.pubUserOrganDao.select(userOrgan);

		List<PubOrganVo> ovs = new ArrayList<PubOrganVo>();
		for (PubUserOrgan uo : uos) {
			PubUserExtra userExtra = new PubUserExtra();
			userExtra.setUserId(userId);
			userExtra.setEntId(uo.getEntId());
			userExtra.setUserState("E");
			userExtra = (PubUserExtra) this.pubUserExtraDao.selectOne(userExtra);
			if (userExtra != null) {
				PubOrganVo organVo = selectOrganById(uo.getEntId());
				if ("1".equals(userExtra.getIsDefault())) {
					organVo.setDefault(true);
				} else {
					organVo.setDefault(false);
				}
				if (null != organVo) {
					ovs.add(organVo);
				}
			}
		}
		return ovs;
	}
}
